package com.cinyi.cyds.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

public class HttpUtil
{
    protected static Log logger = LogFactory.getLog(HttpUtil.class);
    
    // 客户端版本相关
    public static final String appID = "2";
    public static String VERSION_CODE = "250";
    public static String DEVICEINFO = "platform-brand-model-release: android-Lenovo-Lenovo S898t-4.2.2";
    
    public String doSimplePost(String postUrl,Map<String,String> params) throws IOException
    {
        /**
         * 首先要和URL下的URLConnection对话。 URLConnection可以很容易的从URL得到。比如： // Using java.net.URL and //java.net.URLConnection
         * 使用页面发送请求的正常流程：在页面http://www.faircanton.com/message/loginlytebox.asp中输入用户名和密码，然后按登录， 跳转到页面http://www.faircanton.com/message/check.asp进行验证 验证的的结果返回到另一个页面
         * 使用java程序发送请求的流程：使用URLConnection向http://www.faircanton.com/message/check.asp发送请求 并传递两个参数：用户名和密码 然后用程序获取验证结果
         */
        URL url = new URL(postUrl);
        URLConnection connection = url.openConnection();
        /**
         * 然后把连接设为输出模式。URLConnection通常作为输入来使用，比如下载一个Web页。 通过把URLConnection设为输出，你可以把数据向你个Web页传送。下面是如何做：
         */
        connection.setDoOutput(true);
        /**
         * 最后，为了得到OutputStream，简单起见，把它约束在Writer并且放入POST信息中，例如： ...
         */
        OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
        
        StringBuffer parameters = new StringBuffer();
        /** send common parameters **/
        
        /***/
        
        if(params != null){
            for (Map.Entry<String, String> entry : params.entrySet()) {
                parameters.append("&").append(entry.getKey()+"="+entry.getValue()); // 向页面传递数据。post的关键所在！
            }  
            logger.debug(url+parameters.toString());
            out.write(parameters.toString());
        }
        
        // remember to clean up
        out.flush();
        out.close();
        // 一旦发送成功，用以下方法就可以得到服务器的回应：
        String sCurrentLine;
        sCurrentLine = "";
        InputStream l_urlStream;
        l_urlStream = connection.getInputStream();
        // 传说中的三层包装阿！
        BufferedReader l_reader = new BufferedReader(new InputStreamReader(l_urlStream));
        StringBuffer sb = new StringBuffer();
        while ((sCurrentLine = l_reader.readLine()) != null)
        {
            sb.append(sCurrentLine);
        }
        return sb.toString() ;
    }

    /**
     * 
     * @param url
     * @param parameters
     * @param uid       
     * @param deviceId
     * @param token
     * @return
     */
    public String doClientPost(String url,List<NameValuePair> parameters,String uid,String deviceId,String token)
    {
        String result = "";
        HttpPost httpRequst = new HttpPost(url);//创建HttpPost对象
        DefaultHttpClient client = null;
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("appId", appID));
        params.add(new BasicNameValuePair("appBuildCode", VERSION_CODE));
        params.add(new BasicNameValuePair("deviceInfo", DEVICEINFO));        
        params.add(new BasicNameValuePair("deviceId", deviceId==null?"":deviceId));
        params.add(new BasicNameValuePair("uid",uid==null?"":uid));
        params.add(new BasicNameValuePair("token", token==null?"":token));
        logger.info("deviceid:"+deviceId);
        for(NameValuePair p : parameters){
            params.add(p);
        }
        
        try {
            //追加加密字段
            String deviceToken = encrypt(params);
            params.add(new BasicNameValuePair("deviceToken", deviceToken));
            
            client = new DefaultHttpClient();
            client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000);
            client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 10000    );
            
            httpRequst.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));
            HttpResponse httpResponse = client.execute(httpRequst);
            if(httpResponse.getStatusLine().getStatusCode() == 200)
            {
                HttpEntity httpEntity = httpResponse.getEntity();
                result = EntityUtils.toString(httpEntity);//取出应答字符串
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            result = e.getMessage().toString();
        }
        catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            result = e.getMessage().toString();
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            result = e.getMessage().toString();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            result = e.getMessage().toString();
        }finally{
        	if(client != null)
        		client.clearResponseInterceptors();
        }
        return result;
    }
    

    public String encrypt(List<NameValuePair> parameter) throws NoSuchAlgorithmException{
        MessageDigest sha = MessageDigest.getInstance("SHA-512");
        Map map=new HashMap();
        if (parameter != null && parameter.size() > 0) {
            for (NameValuePair p : parameter) {
                map.put(p.getName(), p.getValue());
            }
        }
        //得到key的字典顺序排序的list
        Set sets=map.keySet();
        List list=new ArrayList(sets);
        Collections.sort(list);

        /**
         * 用参数构造成{"key":"value","key":"value}形式的字符串，用以提取参数特征
         */
        String json = "{";
        for(Object key:list){
               //System.out.print(key+","+map.get(key)+"  ");
               json +="\"";
               json +=(String)key;
               json +="\"";
               json +=":";
               json +="\"";
               json +=(String)map.get(key);
               json +="\"";
               json += ",";
              }
        //去掉最后一个逗号
        json = json.substring(0, json.length() -1);

        json += "}";
        
//        logger.info("encrpyt json:" +  json);
        
        byte[] srcBytes;
        try {
            srcBytes = json.getBytes("utf-8");
            //使用srcBytes更新摘要  
            sha.update(srcBytes);  
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  

        //完成哈希计算，得到result  
        byte[] resultBytes = sha.digest();  

        //转成16进制
        StringBuffer sb = new StringBuffer();  
        for(int i = 0; i < resultBytes.length; i ++){  
            int val = ((int) resultBytes[i]) & 0xff;
            if (val < 16)
                sb.append("0"); 
            sb.append(Integer.toHexString(val));
        }  

        //取0、2､4､6､8....共32字节
        String fingerprint = sb.toString();  
        String strRes ="";
        for(int i = 0; i < 32; i ++)
            strRes += fingerprint.charAt(i*2);

        return strRes;
    }
    
}
